self-healing tips.md
---------------------


# Comprehensive Self-Healing Summary: ProMedic1 Infrastructure 2.0

This document serves as the definitive reference for the infrastructure remediations completed on the `promedic1.com` server. It contains the full source code for the most critical logic established to ensure long-term stability and security.

## 🕒 Progression Timeline

### Phase 1: Infrastructure Audit & Root Cause Analysis
- **Finding**: Detected a `SyntaxError` in the IELTS `premium-features.pb.js` hook (`clientIp` redeclared).
- **Finding**: Identified 19GB of leaked screenshots in `/root/monitoring-agent/` causing disk pressure.
- **Finding**: Noticed redundant security headers in Caddy causing browser console warnings.

### Phase 2: Robust Hook Orchestration
- **Action**: Refactored all `premium-features.pb.js` files using Block Scopes/IIFEs.
- **Standard**: All hooks now wrap logic in `(function() { ... })();` to prevent global namespace pollution and redeclaration errors.

### Phase 3: Caddy Performance Hardening
- **Action**: Implemented `immutable` caching and consolidated security headers.
- **Standard**: Replaced `localhost` with `127.0.0.1` for zero-DNS resolution latency on internal proxies.

### Phase 4: Self-Healing Maintenance
- **Action**: Enhanced `server-watchdog` and created `pb-integrity-check.sh`.
- **Standard**: Automated 5GB screenshot cleanup and HTTP 400 recovery logic.

---

## 💻 Full Reference: Robust Hook Pattern
This template was applied to **Coach**, **Diet**, and **IELTS** to standardize security and prevent crashes.

```javascript
/// <reference path=\"../pb_data/types.d.ts\" />

(function() {
    const BOT_TOKEN = $os.getenv(\"BOT_TOKEN_VAR\") || \"\";
    const CHAT_ID = $os.getenv(\"CHAT_ID_VAR\") || \"\";

    // ═══════════════════════════════════════════════════════════════════
    // STANDARDIZED AUTH & RATE LIMITING
    // ═══════════════════════════════════════════════════════════════════
    routerAdd(\"POST\", \"/api/custom/submit-approval\", (e) => {
        // 1. Lazy-Init Rate Limiter
        if (!globalThis._submitApprovalRate) {
            globalThis._submitApprovalRate = { store: {}, windowMs: 30 * 60 * 1000, max: 3 };
        }
        var rl = globalThis._submitApprovalRate;
        var ip = \"unknown\";
        try { ip = e.requestInfo().remoteAddr || \"unknown\"; } catch (err) {}
        
        // 2. Standardized Auth Check
        const authHeader = e.request.header.get(\"Authorization\") || \"\";
        const token = authHeader.replace(/^Bearer\\s+/i, \"\");
        var authRecord = null;
        if (token) {
            try { authRecord = $app.findAuthRecordByToken(token); } catch (err) {}
        }
        if (!authRecord) {
            return e.json(401, { error: \"You must be logged in to submit an approval request.\" });
        }

        // 3. Logic with localized variables (Preventing SyntaxErrors)
        const body = e.requestInfo().body || {};
        const phone = (body.phone || \"\").trim();
        // ... Telegram notification and DB record creation ...
    });
})();
```

---

## 💻 Full Reference: Server Watchdog 2.1
Located at: `/usr/local/bin/server-watchdog`

```bash
#!/bin/bash
# Version: 2.1 (Enhanced with self-healing cleanup)

LOG_TAG=\"server-watchdog\"
SCREENSHOT_DIR=\"/root/monitoring-agent/screenshots\"
SCREENSHOT_MAX_GB=5

# 1. Automated Disk Cleanup
if [ -d \"$SCREENSHOT_DIR\" ]; then
  CURRENT_SIZE_KB=$(du -s \"$SCREENSHOT_DIR\" | awk '{print $1}')
  MAX_SIZE_KB=$((SCREENSHOT_MAX_GB * 1024 * 1024))
  if [ \"$CURRENT_SIZE_KB\" -gt \"$MAX_SIZE_KB\" ]; then
    echo \"[$LOG_TAG] Screenshot directory exceeds ${SCREENSHOT_MAX_GB}GB - purging old files...\"
    find \"$SCREENSHOT_DIR\" -type f -mtime +1 -delete
  fi
fi

# 2. HTTP Health Recovery (Auto-restart on 400/500 errors)
for entry in \"${HEALTH_CHECKS[@]}\"; do
  IFS='|' read -r name url service <<< \"$entry\"
  if ! curl -sf --max-time 8 \"$url\" > /dev/null 2>&1; then
    echo \"[$LOG_TAG] $name not responding - restarting $service...\"
    systemctl restart \"$service\"
  fi
done
```

---

## 💻 Full Reference: Caddy Performance Pattern
Located in: `/etc/caddy/Caddyfile`

```caddy
# Performance Optimization: Direct IP bypasses DNS resolution
reverse_proxy 127.0.0.1:8090 

# Aggressive Static Caching (immutable)
@staticAssets {
    path /assets/*
    path *.js *.css *.woff2 *.woff *.ttf *.png *.jpg *.svg *.ico *.webp
}
header @staticAssets Cache-Control \"public, max-age=31536000, immutable\"

# Redundant Header Elimination (Consolidated block)
header {
    Strict-Transport-Security \"max-age=63072000; includeSubDomains; preload\"
    X-Content-Type-Options \"nosniff\"
    X-Frame-Options \"DENY\"
    Content-Security-Policy \"...\"
    -Server
    -X-Powered-By
}
```

## ✅ Final State Verification
*   **PocketBase**: No SyntaxErrors in logs; standardized IIFE scopes active.
*   **Caddy**: Zero redundant header warnings; aggressive caching enabled.
*   **System**: Automated screenshot cleanup and watchdog recovery active.

**This document should be used as the primary reference for any future assistant working on the ProMedic1 infrastructure.**
